package com.jelly.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jelly.entity.MarkerCallOut;
import com.jelly.entity.MarkerConstant;
import com.jelly.entity.MarkerPosition;
import com.jelly.mapper.MarkerCalloutMapper;
import com.jelly.mapper.MarkerConstantMapper;
import com.jelly.mapper.MarkerPositionMapper;
import com.jelly.query.CircleCenterQuery;
import com.jelly.query.ShareForm;
import com.jelly.redis.RedisUtils;
import com.jelly.service.MarkerPositionService;
import com.jelly.vo.MarkerCallOutVo;
import com.jelly.vo.MarkersInfoVo;
import com.jelly.vo.MarkersPosVo;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class MarkerPositionServiceImpl implements MarkerPositionService {
	@Resource
	private MarkerPositionMapper markerPositionMapper;
	@Resource
	private MarkerConstantMapper markerConstantMapper;
	@Resource
	private RedisUtils redisUtils;
	@Resource
	private MarkerCalloutMapper markerCalloutMapper;

	@Transactional
	@Override
	public void addMarkerPosition(MarkerPosition marker) {

		int num = markerPositionMapper.insert(marker);
		log.info("添加标点{},数据库返回结果{}",marker,num);
		if (num > 0) {
			MarkersInfoVo infoVo = new MarkersInfoVo();
			BeanUtils.copyProperties(marker, infoVo);
			redisUtils.geoAdd(infoVo);
		}
	}

	@Transactional
	@Override
	public void deleteMarkersPosition(Long id) {
		MarkerPosition markers = markerPositionMapper.selectById(id);
		if (markers != null) {
			markerPositionMapper.deleteById(id);
			redisUtils.geoRemove(markers.getMember());
		}
	}

	@Override
	public List<MarkersPosVo> finAll() {
		List<MarkerPosition> list = markerPositionMapper.selectList(null);
		MarkerConstant constant = findMarkerConstant();
		MarkerCallOut callout = findMarkerCallOut();
		List<MarkersPosVo> posList = new ArrayList<>();
		list.forEach(item -> {
			MarkersPosVo posVo = new MarkersPosVo();
			BeanUtils.copyProperties(constant, posVo);
			BeanUtils.copyProperties(item, posVo);
			MarkerCallOutVo calloutVo = new MarkerCallOutVo();
			BeanUtils.copyProperties(callout, calloutVo);
			calloutVo.setContent(item.getTitle());
			posVo.setCallout(calloutVo);
			posList.add(posVo);
		});
		return posList;
	}

	private MarkerConstant findMarkerConstant() {
		QueryWrapper<MarkerConstant> query = new QueryWrapper<>();
		query.eq("enabled", 1);
		MarkerConstant constant = markerConstantMapper.selectOne(query);
		return constant;
	}

	private MarkerCallOut findMarkerCallOut() {
		QueryWrapper<MarkerCallOut> query = new QueryWrapper<>();
		query.eq("enabled", 1);
		MarkerCallOut callout = markerCalloutMapper.selectOne(query);
		return callout;
	}

	@Override
	public List<MarkersPosVo> findMarkersByCircle(CircleCenterQuery query) {

		// 从redis中查询附近的标点
		GeoResults<RedisGeoCommands.GeoLocation<Object>> result = redisUtils.geoRadius(query);
		log.info("通过名字附近的人：{}", result);
		if (result.iterator().hasNext()) { // 如果查到坐标
			// 从数据库中查找标记常量信息，后期优化可从缓存中查询
			MarkerConstant constant = findMarkerConstant();
			MarkerCallOut callout = findMarkerCallOut();
			List<GeoResult<GeoLocation<Object>>> markers = result.getContent();
			List<MarkersPosVo> list = new ArrayList<>();
			markers.forEach(item -> {
				GeoLocation<Object> marker = item.getContent();
				String name = (String) marker.getName();// name=1669643304603631618:111 -->id:title
				String[] param = name.split(":");
				Point point = marker.getPoint();
				MarkersPosVo mposVo = new MarkersPosVo();
				BeanUtils.copyProperties(constant, mposVo);
				mposVo.setId(Long.valueOf(param[0]));
				mposVo.setTitle(param[1]);
				mposVo.setLongitude(String.valueOf(point.getX()));
				mposVo.setLatitude(String.valueOf(point.getY()));
				MarkerCallOutVo calloutVo = new MarkerCallOutVo();
				BeanUtils.copyProperties(callout, calloutVo);
				calloutVo.setContent(param[1]);
				mposVo.setCallout(calloutVo);
				list.add(mposVo);
			});
			return list;
		}
		return null;
	}

	@Override
	public MarkerPosition findById(Long markerId) {
		return markerPositionMapper.selectById(markerId);
	}

	@Override
	public List<MarkersPosVo> findByUserId(Long userId) {
		QueryWrapper<MarkerPosition> query = new QueryWrapper<>();
		query.eq("user_id", userId);
		List<MarkerPosition> list = markerPositionMapper.selectList(query);
		MarkerConstant constant = findMarkerConstant();
		MarkerCallOut callout = findMarkerCallOut();
		List<MarkersPosVo> posList = new ArrayList<>();
		list.forEach(item -> {
			MarkersPosVo posVo = new MarkersPosVo();
			BeanUtils.copyProperties(constant, posVo);
			BeanUtils.copyProperties(item, posVo);
			MarkerCallOutVo calloutVo = new MarkerCallOutVo();
			BeanUtils.copyProperties(callout, calloutVo);
			calloutVo.setContent(item.getTitle());
			posVo.setCallout(calloutVo);
			posList.add(posVo);
		});
		return posList;
	}
	
	@Transactional
	@Override
	public void sharePoint(ShareForm form) {
		MarkerPosition position = markerPositionMapper.selectById(form.getId());
		position.setShare(form.getShare());
		markerPositionMapper.updateById(position);
	}
	
	@Transactional
	@Override
	public void updatePoint(MarkerPosition position) {
		markerPositionMapper.updateById(position);
	}
	
	@Transactional
	@Override
	public void deletePoint(Long id) {
		markerPositionMapper.deleteById(id);
	}

	@Override
	public List<MarkerPosition> findPointByUserId(Long userId) {
		QueryWrapper<MarkerPosition> query = new QueryWrapper<>();
		query.eq("user_id", userId);
		return markerPositionMapper.selectList(query);
	}
}
